import Sampling from "./Sampling";
import Chart from "@/components/Chart";
import { formatTime } from "@/lib/utils/time";
import { getChartOption } from "@/lib/utils/chartOptions";
import ArrowUpIcon from "@/assets/icons/arrow-up.svg?jsx";
import ArrowDownIcon from "@/assets/icons/arrow-down.svg?jsx";
import ArrowRightIcon from "@/assets/icons/arrow-right.svg?jsx";
import ThermometerIcon from "@/assets/images/thermometer.png?jsx";
import WaterIcon from "@/assets/images/water.png?jsx";
import PressureGaugeIcon from "@/assets/images/pressure-gauge.png?jsx";
import useFetch from "@/lib/hooks/useFetch";
import { getDeviceRunningStatus } from "@/lib/api/deviceStatus";
import { useAtomValue } from "jotai";
import { tokenAtom } from "@/store/user";
import type {
  IDeviceFixModeRunningStatus,
  IDeviceProgramModeRunningStatus,
} from "@/lib/types";
import { Spin } from "antd";
import { useEffect, useMemo, type ReactNode } from "react";
import computeTimeDuration from "@/lib/utils/computeTimeDuration";
import { useDeviceContext } from "@/providers/DeviceProvider";
import RealtimeOverviewChart from "./RealtimeOverviewChart";

type StatusProps = {}; // eslint-disable-line
export default function Status(props: StatusProps) {
  const { device } = useDeviceContext();
  const token = useAtomValue(tokenAtom);
  const mode = device!.mode;
  const deviceId = device!.deviceId;

  const {
    data,
    isLoading,
    isPending,
    refetch: handleLoadDeviceRunningStatus,
    cancel: handleCancelLoadDeviceRunningStatus,
  } = useFetch({
    fetchFn: (id: number, signal: AbortSignal) =>
      getDeviceRunningStatus(id, token, signal).then((res) => {
        if (res.code !== 200) {
          throw res;
        }
        return res.data;
      }),
  });

  useEffect(() => {
    let timer: Timer;
    function loop() {
      handleCancelLoadDeviceRunningStatus();
      handleLoadDeviceRunningStatus(deviceId);
      timer = setTimeout(loop, 5000);
    }

    loop();

    return () => {
      clearTimeout(timer);
    };
  }, [
    mode,
    deviceId,
    handleCancelLoadDeviceRunningStatus,
    handleLoadDeviceRunningStatus,
  ]);

  return (
    <div className="relative flex h-full">
      <div className="relative h-full min-w-0 basis-1/3 dark:bg-[#0e0e0e]">
        {/* <Sampling /> */}
        <div className="h-full overflow-y-auto p-4">
          {isPending || !data ? (
            <Spin>
              <div className="h-20"></div>
            </Spin>
          ) : (
            <>
              <div className="mb-1 grid grid-cols-2 border-b pb-1 text-sm">
                <div>
                  <span className="inline-block w-20 text-center font-bold dark:text-[#606060]">
                    委托单号
                  </span>
                  <span>{data.orderNo || "-"}</span>
                </div>
                <div>
                  <span className="inline-block w-20 text-center font-bold dark:text-[#606060]">
                    名称
                  </span>
                  <span>{data.modelName || "-"}</span>
                </div>
                <div>
                  <span className="inline-block w-20 text-center font-bold dark:text-[#606060]">
                    型号
                  </span>
                  <span>{data.modelNo || "-"}</span>
                </div>
                <div>
                  <span className="inline-block w-20 text-center font-bold dark:text-[#606060]">
                    实验项目
                  </span>
                  <span>{data.exerimentItem || "-"}</span>
                </div>
              </div>
              {data.mode === "fix" && (
                <FixModeStatus
                  status={data as IDeviceFixModeRunningStatus}
                  isTime={device!.isTime}
                />
              )}
              {data.mode === "program" && (
                <ProgramModeStatus
                  status={data as IDeviceProgramModeRunningStatus}
                />
              )}
            </>
          )}
        </div>
      </div>
      <div className="flex min-w-0 basis-2/3 flex-col px-10">
        <div className="flex flex-wrap justify-center">
          {device!.isTemperature === 1 && (
            <Card
              header={
                <div className="flex gap-x-2">
                  <ThermometerIcon className="h-12" />
                  <span className="font-bold">℃&nbsp;温度</span>
                </div>
              }
              pv={device!.tPv}
              av={device!.t ? device!.tAv : "OFF"}
              status={device!.t && device!.tStatus}
            />
          )}
          {device!.isHumidity === 1 && (
            <Card
              header={
                <div className="flex gap-x-2">
                  <WaterIcon className="h-12" />
                  <span className="font-bold">%&nbsp;湿度</span>
                </div>
              }
              pv={device!.hPv}
              av={device!.h ? device!.hAv : "OFF"}
              status={device!.h && device!.hStatus}
            />
          )}
          {device!.isPressure === 1 && (
            <Card
              header={
                <div className="flex gap-x-2">
                  <PressureGaugeIcon className="h-12" />
                  <span className="font-bold">Pa&nbsp;压力</span>
                </div>
              }
              pv={device!.pPv}
              av={device!.p ? device!.pAv : "OFF"}
              status={device!.p && device!.pStatus}
            />
          )}
        </div>
        <RealtimeOverviewChart deviceId={deviceId} />
      </div>
    </div>
  );
}

type FixModeStatusProps = {
  status: IDeviceFixModeRunningStatus;
  isTime: number;
};
function FixModeStatus(props: FixModeStatusProps) {
  const { status, isTime } = props;

  const echartsOptions = useMemo(() => {
    const total = status.runTime + status.leftTime;
    const done = (status.runTime / total) * 100;
    return getChartOption(
      done,
      100 - done,
      isTime ? computeTimeDuration(status.leftTime) : "∞",
      isTime ? `${Math.round(100 - done)}%剩余` : undefined,
    );
  }, [status.runTime, status.leftTime, isTime]);

  return (
    <div>
      <div className="text-sm font-bold dark:text-[#606060]">总运行时间</div>
      <div className="border-b pb-8 text-center text-3xl font-bold">
        {computeTimeDuration(status.runTime)}
      </div>
      <div className="mt-2 text-center dark:text-[#606060]">剩余时间</div>
      <Chart className="mx-auto aspect-square w-2/3" options={echartsOptions} />
      {(
        [
          ["开始时间", status.startTime ? formatTime(status.startTime) : ""],
          ["预计结束时间", isTime ? formatTime(status.predictEndTime) : "∞"],
        ] as const
      ).map((item) => (
        <div key={item[0]} className="flex items-baseline">
          <span className="flex-none basis-[120px] dark:text-[#606060]">
            {item[0]}
          </span>
          <span className="text-sm">{item[1]}</span>
        </div>
      ))}
    </div>
  );
}

type ProgramModeStatusProps = {
  status: IDeviceProgramModeRunningStatus;
};
function ProgramModeStatus(props: ProgramModeStatusProps) {
  const { status } = props;
  const echartsOptionsTotal = useMemo(() => {
    const total = status.runTime + status.leftTime;
    const done = (status.runTime / total) * 100;
    return getChartOption(
      done,
      100 - done,
      computeTimeDuration(status.leftTime),
      `${Math.round(100 - done)}%剩余`,
    );
  }, [status.runTime, status.leftTime]);
  const echartsOptionsStep = useMemo(() => {
    const total = status.stepRunTime + status.stepLeftTime;
    const done = (status.stepRunTime / total) * 100;
    return getChartOption(
      done,
      100 - done,
      computeTimeDuration(status.stepLeftTime),
      `${Math.round(100 - done)}%剩余`,
    );
  }, [status.stepRunTime, status.stepLeftTime]);

  return (
    <div>
      <div className="border-b p-2">
        <div className="text-sm font-bold dark:text-[#606060]">总运行时间</div>
        <div className="text-center text-3xl font-bold">
          {computeTimeDuration(status.runTime)}
        </div>
        <div className="text-right">
          <span className="mr-2 text-sm dark:text-[#606060]">步运行时间</span>
          <span>{computeTimeDuration(status.stepRunTime)}</span>
        </div>
      </div>
      <div className="mt-4 flex">
        <div className="aspect-square min-w-0 flex-none basis-1/2">
          <div className="text-center text-sm font-bold dark:text-[#606060]">
            步剩余时间
          </div>
          <Chart
            className="aspect-square w-full"
            options={echartsOptionsStep}
          />
        </div>
        <div className="aspect-square min-w-0 flex-none basis-1/2">
          <div className="text-center text-sm font-bold dark:text-[#606060]">
            总剩余时间
          </div>
          <Chart
            className="aspect-square w-full"
            options={echartsOptionsTotal}
          />
        </div>
      </div>
      <div className="mt-4 flex text-center text-sm">
        <div className="flex-none basis-1/4">
          <div>程序</div>
          <div>{status.programName}</div>
        </div>
        <div className="flex-none basis-1/4">
          <div>步号</div>
          <div>{status.stepNo}</div>
        </div>
        <div className="flex-none basis-1/4">
          <div>段号</div>
          <div>{status.segmentNo}</div>
        </div>
        <div className="flex-none basis-1/4">
          <div>循环数</div>
          <div>{status.loop}</div>
        </div>
      </div>
      <div className="mt-4 text-sm">
        <span className="mr-6 font-bold">开始时间</span>
        <span>{status.startTime ? formatTime(status.startTime) : ""}</span>
      </div>
      <div className="mt-2 text-sm">
        <span className="mr-6 font-bold">结束时间</span>
        <span>
          {status.predictEndTime ? formatTime(status.predictEndTime) : ""}
        </span>
      </div>
      <Loops data={status.loopTimes} />
    </div>
  );
}

const columns = [
  { label: "循环", render: (row) => row.loop },
  { label: "开始时间", render: (row) => formatTime(row.startTime) },
  {
    label: "（预计）结束时间",
    render: (row) => (row.endTime ? formatTime(row.endTime) : ""),
  },
] as { label: string; render: (row: any) => ReactNode }[];
function Loops({
  data,
}: {
  data: {
    loop: number;
    startTime: string;
    endTime: string;
  }[];
}) {
  return (
    <div className="mt-4 border-t pt-2">
      <table className="w-full text-center text-sm">
        <thead>
          <tr className="text-[#7f97a0]">
            {columns.map((column) => (
              <th key={column.label}>{column.label}</th>
            ))}
          </tr>
        </thead>
        <tbody>
          {data.map((row) => (
            <tr key={row.loop}>
              {columns.map((column) => (
                <td key={column.label}>{column.render(row)}</td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

type CardProps = {
  header: JSX.Element;
  pv: number;
  av: number | string;
  status: false | -1 | 0 | 1;
};
function Card(props: CardProps) {
  const { header, pv, av, status } = props;
  return (
    <div className="basis-1/2 p-4">
      <div className="flex flex-col rounded px-4 py-2 dark:bg-[#262626]">
        {header}
        <div className="py-4 text-center text-[40px] tracking-wide">
          {pv.toFixed(1)}
        </div>
        <div className="flex items-center">
          {status === -1 && <ArrowDownIcon height={24} width={15} />}
          {status === 0 && <ArrowRightIcon height={24} width={24} />}
          {status === 1 && <ArrowUpIcon height={24} width={15} />}
          <div className="ml-auto">
            <span className="mr-2 dark:text-[#8b8b8b]">设定值:</span>
            <span>{typeof av === "number" ? av.toFixed(1) : av}</span>
          </div>
        </div>
      </div>
    </div>
  );
}
